using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Threading;
using System.IO;

namespace GIST
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        SpriteFont font;

        Texture2D cloud;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            IsMouseVisible = true;

            /*WebClient client = new WebClient();
            TextReader reader = new StreamReader(client.OpenRead("http://www.google.se/search?tbm=isch&hl=sv&source=hp&biw=1920&bih=1081&q=slott&gbv=2&oq=slott&aq=f&aqi=g9g-s1&aql=1&gs_sm=e&gs_upl=22550l22995l0l23137l5l4l0l0l0l0l194l518l1.3l4l0"));
            Console.WriteLine(reader.ReadLine());*/

            /*try
            {
                TextReader tr = new StreamReader("words.txt");
                while (tr.Peek() != -1)
                {
                    Console.WriteLine(tr.ReadLine());
                }
                tr.Close();
            }
            catch (Exception)
            {
            }*/
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            Services.AddService(typeof(SpriteBatch), spriteBatch);
            font = Content.Load<SpriteFont>("Input");
            cloud = Content.Load<Texture2D>("Header");
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        private KeyboardState lastState;
        private KeyboardState currentState;

        private string currentInput = "";
        public string CurrentInput
        {
            get { return currentInput; }
            private set
            {
                if (font.MeasureString(value).X < 380)
                {
                    string lastInput = currentInput;
                    currentInput = value;
                    if (value == "")
                    {
                        InputPosition = 0;
                    }
                    else
                    {
                        InputPosition += value.Length - lastInput.Length;
                    }
                }
            }
        }

        private void AddInput(char c)
        {
            CurrentInput = CurrentInput.Substring(0, InputPosition) + c + (InputPosition >= CurrentInput.Length ? "" : CurrentInput.Substring(InputPosition, CurrentInput.Length - InputPosition));
        }

        private void RemoveInput()
        {
            CurrentInput = (InputPosition == 0 ? "" : CurrentInput.Substring(0, InputPosition - 1)) + CurrentInput.Substring(InputPosition, CurrentInput.Length - InputPosition);
        }

        private int inputPosition = 0;
        public int InputPosition
        {
            get { return inputPosition; }
            set
            {
                inputPosition = (int)MathHelper.Clamp(value, 0, CurrentInput.Length);
            }
        }

        private static Random random = new Random(DateTime.Now.Millisecond);

        private int counter = 0;
        private int wait = 0;

        private List<string> bannedWords = new List<string>();
        public List<string> BannedWords
        {
            get { return bannedWords; }
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            lastState = currentState;
            currentState = Keyboard.GetState();

            for (int c = (int)Keys.A; c <= (int)Keys.Z; c++)
            {
                if (KeyPress((Keys)c))
                {
                    AddInput((char)c);
                }
            }

            if (KeyPress(Keys.Back) && currentInput.Length > 0)
            {
                RemoveInput();
            }

            if (KeyPress(Keys.Space))
            {
                AddInput(' ');
            }

            if (KeyPress(Keys.Enter) && CurrentInput.Trim() != "" && wait == 0)
            {
                string thoughtIdea = currentInput.Trim();
                if (!BannedWords.Contains(thoughtIdea))
                {
                    Thread creator = new Thread(() => CreateThought(thoughtIdea));
                    creator.Start();

                    TextWriter tw = new StreamWriter("words.txt", true);
                    tw.WriteLine(thoughtIdea);
                    tw.Close();
                }
                CurrentInput = "";
                wait = 60;
            }

            if (wait > 0)
            {
                wait--;
            }

            if (KeyPress(Keys.Left))
            {
                InputPosition--;
            }

            if (KeyPress(Keys.Right))
            {
                InputPosition++;
            }

            if (KeyPress(Keys.F4))
            {
                if (graphics.IsFullScreen)
                {
                    graphics.PreferredBackBufferWidth = 1200;
                    graphics.PreferredBackBufferHeight = 800;
                }
                else
                {
                    DisplayMode mode = GraphicsAdapter.DefaultAdapter.SupportedDisplayModes.Last();
                    graphics.PreferredBackBufferWidth = mode.Width;
                    graphics.PreferredBackBufferHeight = mode.Height;
                }
                graphics.ToggleFullScreen();
            }

            counter++;

            if (Components.Count > 0 && counter % 60 == 0)
            {
                Thought toShow = (Thought)Components[random.Next(Components.Count)];
                if (toShow.Alpha <= 0 && !toShow.FadeIn)
                {
                    toShow.Show();
                }
            }

            base.Update(gameTime);
        }

        private void CreateThought(string thought)
        {
            Components.Add(new Thought(this, thought));
        }

        private bool KeyPress(Keys input)
        {
            return currentState.IsKeyDown(input) && lastState.IsKeyUp(input);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied);

            base.Draw(gameTime);

            spriteBatch.Draw(cloud, new Vector2(GraphicsDevice.Viewport.Width / 2, 0), null, Color.White, 0, new Vector2(cloud.Width / 2f, 0), 1, SpriteEffects.None, 0.0000001f);

            spriteBatch.DrawString(font, currentInput, new Vector2(GraphicsDevice.Viewport.Width / 2 - 195, 33), Color.Black, 0, Vector2.Zero, 1, SpriteEffects.None, 0);

            if (counter % 60 < 40)
            {
                spriteBatch.DrawString(font, "|", new Vector2(GraphicsDevice.Viewport.Width / 2 - 200 + font.MeasureString(currentInput.Substring(0, InputPosition)).X, 33), Color.Black, 0, Vector2.Zero, 1, SpriteEffects.None, 0);

            }

            spriteBatch.End();
        }
    }
}
